package com.gopay.cron.service.log.impl;

import com.gopay.common.domain.log.OperLogDtl;
import com.gopay.common.log.constants.LogOperStatusCd;
import com.gopay.common.log.logxnew.constants.LogCodeConstants;
import com.gopay.common.log.logxnew.dao.OperLogDtlDAO;
import com.gopay.common.util.DateUtils;
import com.gopay.cron.service.log.CorpLoginLogService;
import com.mongodb.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.net.UnknownHostException;
import java.util.*;

/**
 * @author sh.jiao
 * 存量企业登录日志Service实现类
 */
@Service(value = "corpLoginLogService")
public class CorpLoginLogServiceImpl implements CorpLoginLogService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static Mongo m = null;
    private static DB db = null;
    //主机ip
    private @Value("#{webProperties['mongo.host']}") String mongoHost;
    //端口号
    private @Value("#{webProperties['mongo.port']}") String mongoPort;
    //数据库名称
    private @Value("#{webProperties['mongo.databasename']}") String mongoDatabaseName;
    //数据库集合名称
    private @Value("#{webProperties['mongo.mongocollectionname']}") String mongoCollectionName;


    private static final int PAGESIZE = 1000;

    @Resource(name = "operLogDtlDAO")
    private OperLogDtlDAO operLogDtlDAO;

    @Override
    public void transferLog() {
        //获取数据库集合，相当于表
        startMongoDBConn();
        DBCollection dbCol = db.getCollection(mongoCollectionName);
        //查询记录数
        long size = dbCol.count();
        logger.error("共计{}条数据。",size);
        int i = (int)((size + (PAGESIZE-1)) / PAGESIZE);
        for(int j = 0;j<i;j++) {
            List<OperLogDtl> list = new ArrayList<>();
            doTransfer(dbCol,list,(j + 1),PAGESIZE);
            logger.error("需要保存到数据库的数据有{}条。",list.size());
            logger.error("开始执行保存数据......");
            operLogDtlDAO.saveOrUpdateAll(list);
            logger.error("保存成功！");
        }
        stopMondoDBConn();
    }

    private void doTransfer(DBCollection dbCol, List<OperLogDtl> list, int page, int pagesize) {
        DBCursor ret = dbCol.find()//.sort(new BasicDBObject("loginTime", -1)) mongodb的排序很耗内存，超过默认32M会报错，中断程序
                .skip((page - 1) * pagesize).limit(pagesize);
        logger.info("开始读取第{}页，{}条数据。",page,ret.size());
        long start = System.currentTimeMillis();
        while(ret.hasNext()){
            BasicDBObject bdbObj = (BasicDBObject) ret.next();
            OperLogDtl operLogDtl = new OperLogDtl();
            if(bdbObj != null){
                String time=bdbObj.getString("loginTime");
                long l = Long.parseLong(time);
                Date date = new Date(l); // long类型转成Date类型
                operLogDtl.setOperTs(date);
                String custId=bdbObj.getString("custId");
                if (StringUtils.isNotBlank(custId) && custId.length()>50) {
                    custId="";
                }
                operLogDtl.setLaunchCustId(custId);
                String username=bdbObj.getString("username");
                if (StringUtils.isNotBlank(username) && username.length()>100) {
                    username="";
                }
                operLogDtl.setLaunchUserName(username);
                String eorm = bdbObj.getString("eorm");
                if (eorm != null && eorm.length()<50) {
                    operLogDtl.setLaunchUserId(eorm);
                }
                String merName=bdbObj.getString("merName");
                if (StringUtils.isNotBlank(merName) && merName.length()>100) {
                    merName="";
                }
                operLogDtl.setLaunchCustName(merName);
                String ip=bdbObj.getString("ip");
                if (StringUtils.isNotBlank(ip) && ip.length()>20) {
                    ip="";
                }
                operLogDtl.setLocalIp(ip);
                String oprId=bdbObj.getString("oprId");
                if (StringUtils.isNotBlank(oprId) && oprId.length()>50) {
                    oprId="";
                }
                operLogDtl.setOperId(oprId);
                operLogDtl.setRemark("(oldData)");
                String result = bdbObj.getString("result");
                operLogDtl.setStatus(LogOperStatusCd.SUCCESS.value);
                if ("fail".equals(result)) {
                    operLogDtl.setStatus(LogOperStatusCd.FAILED.value);
                }
                operLogDtl.setPlatform(LogCodeConstants.PLATFORM_PORTAL);
                operLogDtl.setCategory(LogCodeConstants.CATEGORY_CUST);
                operLogDtl.setModules(LogCodeConstants.MODULE_BASICINFO);
                operLogDtl.setOperTypeCd(LogCodeConstants.PORTAL_CUST_BASICINFO_02);

                String userType = bdbObj.getString("userType");
                String loginSource = bdbObj.getString("loginSource");//登录来源
                String phoneModel = bdbObj.getString("phoneModel");//手机型号
                String deviceType = bdbObj.getString("deviceType");//设备类型
                String deviceId = bdbObj.getString("deviceId");//设备ID
                String isRootFlag = bdbObj.getString("isRootFlag");//是否被root
                if (StringUtils.isNotBlank(phoneModel) || StringUtils.isNotBlank(deviceId) || StringUtils.isNotBlank(isRootFlag)){
                    continue;//DPS登录不同步1.0之前记录
                    //operLogDtl.setTargetUserId(userType);
                    //operLogDtl.setRemark(loginSource+"-"+phoneModel+"-"+deviceType+" ::: "+"设备ID:"+deviceId+
                    //",是否被root:"+isRootFlag+"(oldData)");
                    //operLogDtl.setPlatform(LogCodeConstants.PLATFORM_DPS);
                    //operLogDtl.setOperTypeCd(LogCodeConstants.DPS_CUST_BASICINFO_05);
                }
                list.add(operLogDtl);
            }
        }
        logger.info("读取并保存mongodb数据库第{}页数据结束，耗时{}ms",page,(System.currentTimeMillis()-start));
    }

    /**
     * 获取mongodb数据库连接
     */
    private void startMongoDBConn(){
        try {
            //Mongo(p1, p2):p1=>IP地址     p2=>端口
            m = new Mongo(mongoHost, Integer.parseInt(mongoPort));
            //根据mongodb数据库的名称获取mongodb对象
            db = m.getDB(mongoDatabaseName);
            //校验用户密码是否正确
        } catch (UnknownHostException e) {
            logger.error("无效连接！",e);
        } catch (MongoException e) {
            logger.error("连接失败",e);
        }
    }

    /**
     * 关闭mongodb数据库连接
     */
    private void stopMondoDBConn(){
        if (null != m) {
            if (null != db) {
                // 结束Mongo数据库的事务请求
                try {
                    db.requestDone();
                } catch(Exception e) {
                    logger.error("结束Mongo数据库的事务请求失败！",e);
                }
            }
            try
            {
                m.close();
            } catch(Exception e) {
                logger.error("关闭连接失败！",e);
            }
            m = null;
            db = null;
        }
    }


    /**
     * 查询分页的
     */
    private List<Map<String,Object>> readColData() {

        List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
        //获取数据库集合，相当于表
        DBCollection dbCol = db.getCollection(mongoCollectionName);
        DBCursor ret = dbCol.find().sort(new BasicDBObject("loginTime", -1));
        logger.info("开始读取数据了.....");
        while(ret.hasNext()){
            BasicDBObject bdbObj = (BasicDBObject) ret.next();
            Map<String,Object> cll = new HashMap<>();
            if(bdbObj != null){
                String time=bdbObj.getString("loginTime");
                long l = Long.parseLong(time);
                Date date = new Date(l); // long类型转成Date类型
                String loginTime= DateUtils.format(date, "yyyy-MM-dd HH:mm:ss");
                String custId=bdbObj.getString("custId");
                String username=bdbObj.getString("eorm");
                String merName=bdbObj.getString("merName");
                String ip=bdbObj.getString("ip");
                String oprId=bdbObj.getString("oprId");

                cll.put("custId",custId);
                cll.put("username",username);
                cll.put("merName",merName);
                cll.put("loginTime",loginTime);
                cll.put("ip",ip);
                cll.put("operId",oprId);

                list.add(cll);
            }
        }
        logger.info("读取mongodb数据库结束");

        return list;

    }

    public String getMongoHost() {
        return mongoHost;
    }


    public void setMongoHost(String mongoHost) {
        this.mongoHost = mongoHost;
    }


    public String getMongoPort() {
        return mongoPort;
    }


    public void setMongoPort(String mongoPort) {
        this.mongoPort = mongoPort;
    }


    public String getMongoDatabaseName() {
        return mongoDatabaseName;
    }


    public void setMongoDatabaseName(String mongoDatabaseName) {
        this.mongoDatabaseName = mongoDatabaseName;
    }


    public String getMongoCollectionName() {
        return mongoCollectionName;
    }


    public void setMongoCollectionName(String mongoCollectionName) {
        this.mongoCollectionName = mongoCollectionName;
    }
}
